/*
Copyright 2011 Raymond Giorgi

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

   http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
 */

package edu.pitt.cs3530.reactors;

import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import edu.pitt.cs3530.configuration.FrontEndConfiguration;
import edu.pitt.cs3530.controllers.ReactorListener;
import edu.pitt.cs3530.misc.Mutexs;

/**
 * This thread calculates how many requests have missed their deadline There are
 * two deadlines. An regular and a lower. If the regular hits, we consider the
 * request 'in time'. If the lower hits, we consider the request 'early' and can
 * scale down the system (if rules allow)
 */
public abstract class ReactorThread extends Thread {
	protected String directory;
	protected int removeAfter;
	protected double deadline;
	protected int madeDeadline;
	protected int missedDeadline;
	protected long sleepTime;
	protected double lowerDeadline;
	protected long oldTime;
	protected List<ReactorListener> listeners;

	public ReactorThread(long deadline, long lowerDeadline, long sleepTime,
			long oldTime, String qosName, Map<String, String> parameterMap) {
		this.directory = FrontEndConfiguration.getInstance()
				.getTemporaryDirectory();
		this.deadline = deadline;
		this.sleepTime = sleepTime;
		this.lowerDeadline = lowerDeadline;
		this.oldTime = oldTime;
		listeners = new LinkedList<ReactorListener>();
	}

	@Override
	public void run() {
		System.out.println("start");
		while (true) {
			long start = System.currentTimeMillis();
			generateResults();
			this.alertListeners();
			// System.out.println("Total processing:"
			// + (System.currentTimeMillis() - start));
			try {
				sleep(sleepTime);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

	private void alertListeners() {
		for (ReactorListener rl : listeners) {
			rl.alertResponseListener(this);
		}
	}

	/**
	 * Determine which requests are early, late, etc.
	 */
	protected abstract void generateResults();

	/**
	 * Add a listener to be alerted when new calculations are gathered
	 * 
	 * @param listener
	 */
	public void addListener(ReactorListener listener) {
		listeners.add(listener);
	}

	/**
	 * Remove a listener from the list
	 * 
	 * @param listener
	 */
	public void removeListener(ReactorListener listener) {
		listeners.remove(listener);
	}

	/**
	 * Set how many requests are made, how many are missed, etc
	 * 
	 * @param madeDeadline
	 * @param missedDeadline
	 */
	protected void setMade(int madeDeadline, int missedDeadline) {
		Mutexs.lockDeadlineMutex();
		this.madeDeadline = madeDeadline;
		this.missedDeadline = missedDeadline;
		Mutexs.unlockDeadlineMutex();
	}

	/**
	 * @return the number of made requests
	 */
	public abstract int getMade();

	/**
	 * @return the number of missed requests
	 */
	public abstract int getMissed();

	/**
	 * @return the number of requests completed early
	 */
	public abstract int getMadeInLowerDeadline();

	/**
	 * @return the total number of requests
	 */
	public abstract int getTotal();

	/**
	 * @return get the percentage of requests made in the deadline
	 */
	public abstract double getPercentMade();

	/**
	 * @return percentage of requests that missed the deadline
	 */
	public abstract double getPercentMissed();

	/**
	 * @return percentage of requests that made it early
	 */
	public abstract double getPercentMadeInLowerDeadline();
}
